﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Dynamic;

namespace MyDemo.Dynamic
{
    /// <summary>
    /// 动态类型
    /// </summary>
    public class DynamicSamples
    {
        #region Test1

        /// <summary>
        /// 浅谈Dynamic 关键字系列之一:dynamic 就是Object
        /// http://www.cnblogs.com/LoveJenny/archive/2011/07/04/2097031.html
        /// </summary>
        // 微软对此的解释是：
        // 在大多数情况下， dynamic 类型与 object 类型的行为是一样的。
        // 但是，不会用编译器对包含 dynamic 类型表达式的操作进行解析或类型检查。
        // 编译器将有关该操作信息打包在一起，并且该信息以后用于计算运行时操作。
        // 在此过程中，类型 dynamic 的变量会编译到类型 object 的变量中。 因此，类型 dynamic 只在编译时存在，在运行时则不存在。
        public void Test1()
        {
            dynamic dyn = 1;
            object obj = 1;

            Console.WriteLine(dyn.GetType());
            Console.WriteLine(obj.GetType());

            dyn = dyn + 3;
            //obj = obj + 3;

            //dynamic可以隐式的转换成任何类型，并且也可以从其他类型中转换回来
            dynamic dyn2 = (dynamic)1;
            int j = dyn2;

            //下面这句话会无法通过编译,typeof 运算符无法用在动态类型上
            //Console.WriteLine(typeof(dynamic));

            Console.WriteLine(typeof(List<dynamic>));
        }

        #endregion Test1

        #region Test2

        /// <summary>
        /// 浅谈Dynamic 关键字系列之二:调用属性，方法，字段
        /// http://www.cnblogs.com/LoveJenny/archive/2011/07/04/2097694.html
        /// </summary>
        public void Test2()
        {
            // dynamic对象
            dynamic dynProduct = new Product();
            // 设置name字段
            dynProduct.name = "n1";
            // 设置Id属性
            dynProduct.Id = 1;
            dynProduct.Id = dynProduct.Id + 3;
            // 调用ShowProduct方法
            dynProduct.ShowProduct();
            // 设置为字符串
            dynProduct = "123";
            Console.WriteLine(dynProduct);
        }

        private class Product
        {
            public string name;
            public int Id { get; set; }

            public void ShowProduct()
            {
                Console.WriteLine("Id={0} ,Name={1}", Id, name);
            }
        }

        #endregion Test2

        #region Test3

        /// <summary>
        /// 浅谈Dynamic 关键字系列之三（上）:ExpandoObject， DynamicObject， DynamicMetaObject
        /// http://www.cnblogs.com/LoveJenny/archive/2011/07/05/2098578.html
        /// </summary>
        public void Test3()
        {
            dynamic dynEO = new ExpandoObject();
            dynEO.number = 10;
            dynEO.Increment = new Action(() => { dynEO.number++; });

            Console.WriteLine(dynEO.number);
            dynEO.Increment();
            Console.WriteLine(dynEO.number);

            foreach (var property in (IDictionary<string, object>)dynEO)
            {
                Console.WriteLine(property.Key + ": " + property.Value);
            }

            ((INotifyPropertyChanged)dynEO).PropertyChanged += DynamicTest_PropertyChanged; 
            dynEO.ChineseName = "冯珏庆";
            dynEO.NickName = "jack";
        }

        private void DynamicTest_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            Console.WriteLine("属性{0}已更改", e.PropertyName);
        }

        #endregion Test3

    }
}